package com.example.dayu521.sg_oss.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.example.dayu521.sg_oss.conf.prop.LocalFilePro;
import com.example.dayu521.sg_oss.domain.OssIndex;
import com.example.dayu521.sg_oss.domain.OssIndexRecover;
import com.example.dayu521.sg_oss.service.Oss;
import com.example.dayu521.sg_oss.service.OssIndexRecoverService;
import com.example.dayu521.sg_oss.service.OssIndexService;
import com.rabbitmq.client.Channel;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.example.dayu521.oss.Mq;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.nio.file.DirectoryNotEmptyException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.Map;

@Slf4j
@Component
public class OssRecover {

    private Long node_id = null;

    @PostConstruct
    public void init() {
        node_id = redisTemplate.opsForValue().increment("sg-oss.recover.id-generator");
        log.info("当前恢复节点id是:{}", node_id);
    }

    @Resource
    private RedisTemplate<String, Long> redisTemplate;

    @Resource
    private OssIndexService ossIndexService;

    @Resource
    private OssIndexRecoverService ossIndexRecoverService;

    @Resource
    private Oss oss;

    //恢复放到事务中
    //如果存在大量恢复,则事务都会阻塞
    //需要做出决策.决策可以由既定的方式指定.
    // 这里可以使用redis进行次数检测,如果超过100次,则判定恢复失败,那么终止进行中的恢复

    //基于当前状态只能修改不相关的其他状态
    //上传接口必须简单,恢复接口可以复杂
    //redis使用超时时间检测
    @RabbitListener(queues = {"sg_oss.recover.queue.local"},concurrency = "1")
    public void upload_recover_local(@Payload Mq.Recover msg/*, Channel channel,@Header(AmqpHeaders.DELIVERY_TAG) long tag*/){
        //todo 校验msg是文件path
        log.info("收到{}清理文件消息:{}",oss.oss_identify(),msg.obj_name());
        var res = redisTemplate.opsForValue().setIfAbsent("sg-oss.recover.sentinel", node_id, Duration.ofSeconds(1));
        if (!res) {
            log.info("正在排队恢复,请稍后");
            return;
        }
        if(!ossIndexRecoverService.within_transaction_recover(node_id,msg)){
//            channel.basicAck(tag,false);
            return ;
        }
        log.info("恢复成功");
        //返回后 自动确认
    }

    @RabbitListener(queues = {"sg_oss.recover.queue.minio"})
    public void upload_recover_minio(@Payload Mq.Recover msg) {
        upload_recover_local(msg);
    }
}
